[小ネタ]dbtでクエリ実行結果を変数として扱う方法

[小ネタ]dbtでクエリ実行結果を変数として扱う方法

Clock Icon2024.11.14

さがらです。

小ネタなのですが、dbtでクエリ結果を変数として扱う方法について本記事でまとめます。

※下記のStack Overflowの記事の最も投票数が高い投稿を実際に試してみた内容となります。

https://stackoverflow.com/questions/64007239/how-do-we-define-select-statement-as-a-variable-in-dbt

dbtでクエリ結果を変数として扱う方法

早速結論ですが、下記のように記述をすればOKです。

{%- call statement('get_query_result', fetch_result=True) -%}
    select * from customers
{%- endcall -%}

{%- set var_result = load_result('get_query_result')['data'][0][0] -%}

この上で、dbtのModel上で参照したい場合には下記のように記述をすればOKです。[0][0]とすると、1列目の1行目の値を返します。1つ目の[0]が何番目のレコードか、2つ目の[0]何個目のカラムか、を指定する必要があります。

{%- call statement('get_query_result', fetch_result=True) -%}
    select * from customers
{%- endcall -%}

{%- set var_result = load_result('get_query_result')['data'][0][0] -%}

select
    {{ var_result }} as result

2024-11-14_16h26_24

また、日付の値を変数として取得してクエリ上でその変数を日付として扱いたい場合は'で変数を囲んで一度明示的に文字列としてから型変更をしてあげる必要があります。

{%- call statement('get_query_result', fetch_result=True) -%}
    select * from customers
{%- endcall -%}

{%- set var_result = load_result('get_query_result')['data'][0][3] -%}

select
    cast('{{ var_result }}' as date) as result

2024-11-14_16h44_43

裏話

なんでこんな小ネタを投稿したのかというと、Snowflake×dbtでのIncremental Modelの実装時に下記の記事のエラーに遭遇したためです…

https://discourse.getdbt.com/t/how-to-resolve-subquery-containing-correlated-aggregate-function-can-only-appear-in-having-or-select-clause/5031/13

私はこの記事の解決方法ではうまくいかなかったため、本記事で記したように変数化することで解決しました。(以下は実装したコードのイメージです。)

-- 現在のテーブルから最新日時を変数として取得
{% if is_incremental() %}
    {%- call statement('get_latest_time', fetch_result=True) -%}
      select coalesce(max(update_at), '1900-01-01') from {{ this }}
    {%- endcall -%}

    {%- set var_latest_time = load_result('get_latest_time')['data'][0][0] -%}
{% endif %}

-----------
-- 中略
-----------

-- 取得した変数を差分検知の処理に適用
{% if is_incremental() %}
    where update_at > to_timestamp('{{ var_latest_time }}')
{% endif %}

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.